/*  File Name	: Connector.cpp
 *  Author		: Pang Jiacai
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2012-6-25
 *  Description:
 */
#ifndef CONNECTOR_CPP_
#define CONNECTOR_CPP_
#include "Connector.h"
#include <netinet/in.h>

//template<class SVC_HANDLER>
//NonBlock_Handle_Connector<SVC_HANDLER>::NonBlock_Handle_Connector(
//		Connector_Base<SVC_HANDLER> &connector, SVC_HANDLER *svc, long timer_id)
//{
//	this->connector_ = connector;
//	this->svc_handler_ = svc;
//	this->time_id_ = timer_id;
//}
//
//template<class SVC_HANDLER>
//NonBlock_Handle_Connector<SVC_HANDLER>::~NonBlock_Handle_Connector()
//{
//
//}
//
//template<class SVC_HANDLER>
//bool NonBlock_Handle_Connector<SVC_HANDLER>::close(SVC_HANDLER *svc)
//{
//	return false;
//}
//
//template<class SVC_HANDLER>
//SVC_HANDLER *NonBlock_Handle_Connector<SVC_HANDLER>::svc_handler(void)
//{
//	return this->svc_handler_;
//}
//
//template<class SVC_HANDLER>
//int NonBlock_Handle_Connector<SVC_HANDLER>::handle(void) const
//{
//	return this->svc_handler_->get_handle();
//}
//
//template<class SVC_HANDLER>
//long NonBlock_Handle_Connector<SVC_HANDLER>::timer_id(void)
//{
//	return this->time_id_;
//}
//
//template<class SVC_HANDLER>
//void NonBlock_Handle_Connector<SVC_HANDLER>::timer_id(long timer_id)
//{
//	this->time_id_ = timer_id;
//}
//
//template<class SVC_HANDLER>
//int NonBlock_Handle_Connector<SVC_HANDLER>::handle_input(int handle)
//{
//	return 0;
//}
//
//template<class SVC_HANDLER>
//int NonBlock_Handle_Connector<SVC_HANDLER>::handle_output(int handle)
//{
//	return this->connector_.init_svc_handler(svc_handler_->get_handle(),svc_handler_);
//}
//
//template<class SVC_HANDLER>
//int NonBlock_Handle_Connector<SVC_HANDLER>::handle_exception(int handle)
//{
//	return 0;
//}
//
//template<class SVC_HANDLER>
//int NonBlock_Handle_Connector<SVC_HANDLER>::handle_timeout(void)
//{
//	return 0;
//}

/////////////////////////////////////////////////////////////////////

template<class SVC_HANDLER,class PEER_CONNECTOR>
Connector<SVC_HANDLER,PEER_CONNECTOR>::Connector(Reactor *reactor,bool non_block)
{
	this->open(reactor,non_block);
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
Connector<SVC_HANDLER,PEER_CONNECTOR>::~Connector()
{
	if(this->svc_!=NULL && this->new_svc_)
	{
		delete this->svc_;
		this->svc_ = NULL;
	}
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
const PEER_CONNECTOR &Connector<SVC_HANDLER,PEER_CONNECTOR>::connector(void)
{
	return this->connector_;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
int Connector<SVC_HANDLER,PEER_CONNECTOR>::
	init_svc_hanlder(int handle,SVC_HANDLER *svc)
{
	//this->connector_.set_handle(handle);
	svc->set_handle(handle);

	sockaddr_in *addr=NULL;
	if(svc->peer()->get_remote_addr(addr)!=-1)
	{
		this->active_svc_handler(svc);
	}
	else
	{
		svc->close();
	}
	return 0;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
int Connector<SVC_HANDLER,PEER_CONNECTOR>::
	make_svc_handler(SVC_HANDLER *&svc)
{
	if(NULL==svc)
	{
		svc = new SVC_HANDLER();
		if(NULL==svc)
		{
			LOG((ERROR_LOG,"Connector::make_svc_handler error"));
			return -1;
		}
		this->new_svc_ = true;
	}
	svc->reactor(this->reactor());
	return 0;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
int Connector<SVC_HANDLER,PEER_CONNECTOR>::
	connect_svc_handler(SVC_HANDLER *svc,std::string ip,
			int port,TimeValue &timeout,int pro_family,
			int type,int protocol,bool reuseaddr)
{
	return this->connector_.connect(svc->peer(),ip,port,
			timeout,pro_family,type,protocol,reuseaddr);
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
int Connector<SVC_HANDLER,PEER_CONNECTOR>::
	active_svc_handler(SVC_HANDLER *svc)
{
	if(this->non_block_)
	{
		if(svc->peer()->enable(O_NONBLOCK)!=0)
		{
			return -1;
		}
	}
	else if(svc->peer()->disable(O_NONBLOCK)!=0)
	{
		return -1;
	}
	if(svc->open()!=0)
	{
		svc->close();
		return -1;
	}
	return 0;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
std::map<int,int> &Connector<SVC_HANDLER,PEER_CONNECTOR>::
	non_blocking_handles(void)
{
	return this->non_blocking_handles_;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
int Connector<SVC_HANDLER,PEER_CONNECTOR>::
	open(Reactor *reactor,bool non_block)
{
	this->reactor(reactor);
	this->non_block_ = non_block;
	this->svc_ = NULL;
	this->new_svc_ = false;
	return 0;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
int Connector<SVC_HANDLER,PEER_CONNECTOR>::
	connect(std::string ip,int port,SVC_HANDLER *&svc,
			TimeValue timeout,int pro_family,
			int type,int protocol,bool reuseaddr)
{
	int result = this->make_svc_handler(svc);
	if(result!=0)
	{
		return -1;
	}

	result = this->connect_svc_handler(svc,ip,port,
			timeout,pro_family,type,protocol,reuseaddr);

	if(result!=0)
	{
		return -1;
	}
	this->svc_ = svc;

	return this->active_svc_handler(svc);

	/* If the connection hasn't completed and we are using
	 * non-blocking semantics then register
	 * NonBlocking_Connect_Handler with the Reactor so that
	 * it will call us back when the connection is complete or we
	 * timeout, whichever comes first...
	 */
//	if(errno==EWOULDBLOCK && NULL!=this->reactor())
//	{
//		long timer_id = -1;
//		NBCH *nbch = 0;
//		nbch = new NBCH(*this,svc,timer_id);
//		if(NULL==nbch)
//		{
//			return -1;
//		}
//
//		int result =-1;
//		int handle = svc->get_handle();
//		ReactorMask mask = EventHandler::CONNECT_MASK;
//
//		LockGuardReturn(RT_MUTEX,lock,this->reactor()->lock(),-1);
//		result = this->reactor()->register_handler(handle,nbch,mask);
//		if (result == 0)
//		{
//			this->non_blocking_handles().insert(std::pair<int,int>(handle,handle));
//
//			this->reactor()->schudle_timer(nbch,0,500);
//	        errno = EWOULDBLOCK;
//		}
//		else
//		{
//			this->reactor()->remove_handler(handle,svc,mask);
//			this->non_blocking_handles().erase(handle);
//		}
//	}
//	return -1;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
int Connector<SVC_HANDLER,PEER_CONNECTOR>::close(void)
{
	return this->connector_.close();
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
void Connector<SVC_HANDLER,PEER_CONNECTOR>::reactor(Reactor *reactor)
{
	this->reactor_ = reactor;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
Reactor *Connector<SVC_HANDLER,PEER_CONNECTOR>::reactor (void) const
{
	return this->reactor_;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
SVC_HANDLER *Connector<SVC_HANDLER,PEER_CONNECTOR>::svc(void)
{
	return this->svc_;
}

template<class SVC_HANDLER,class PEER_CONNECTOR>
void Connector<SVC_HANDLER,PEER_CONNECTOR>::svc(SVC_HANDLER *s)
{
	this->svc_ = s;
}

#endif /*CONNECTOR_CPP_*/
